<script>
import { Button, Modal } from 'view-design'
import { Observer, typeOf } from '@/shared/Observer'

export default {
  data () {
    return {
      dialogs: [],
      btns: [
        { label: '取消', value: 'cancel', loading: false },
        {
          label: '确定',
          value: 'sure',
          type: 'primary',
          loading: false
        }
      ],
      dialogWidth: {
        medium: '1200px',
        small: '934px',
        mini: '490px'
      },
      commonProps: {
        maskClosable: false,
        transfer: false
      },
      title: 'title',
      value: false
    }
  },
  computed: {

  },
  created () {
    Observer.subscribe('MModalShow', (op = {}) => this.show(op))
    Observer.subscribe('MModalClose', (invertedNum = 1) => this.back(invertedNum))
    Observer.subscribe('MModalCloseAll', () => this.closeAll())
  },
  methods: {
    initCarrierOptions (options) {
      const { width, size } = options
      const modalWidth = width || this.dialogWidth[size || 'mini']
      const { value } = this
      return { ...this.commonProps, width: modalWidth, ...options, value }
    },
    closeAll () {
      // eslint-disable-next-line no-return-assign
      this.dialogs.forEach(d => d.value = false)
      setTimeout(() => {
        this.dialogs = []
      }, 300)
    },
    onVisibleChange (visible, d) {
      if (!visible) {
        if (d.onClose && typeOf(d.onClose, ['function', 'asyncfunction'])) { d.onClose() }
        this.back()
      } else {
        if (d.onOpen && typeOf(d.onOpen, ['function', 'asyncfunction'])) { d.onOpen() }
      }
    },
    back (invertedNum = 1) {
      const len = this.dialogs.length
      const setDialog = this.dialogs[len - 1]
      invertedNum = invertedNum > len ? len : invertedNum
      setDialog.value = false
      setTimeout(() => {
        this.dialogs.splice(len - invertedNum, len)
      }, 300)
    },
    show (options = {}) {
      this.value = false
      const nowLen = this.dialogs.length
      this.dialogs.splice(nowLen, 0, this.initCarrierOptions(options))
      this.$nextTick(() => {
        this.dialogs[nowLen].value = true
      })
    },
    renderDialogDefault (h, dialogData) {
      const { defaultProps, _index } = dialogData
      const content = dialogData.render
      const children = []
      switch (typeOf(content)) {
        case 'object':children.unshift(h(content, { props: defaultProps, ref: `default-${_index}`, class: 'm-carrier-conetnt' }))
          break
        case 'string':children.unshift(h('div', { domProps: { innerHTML: content } }))
          break
        case 'function':children.unshift(content(h))
          break
      }
      return h('div', { class: 'm-carrier-body' }, [
        h('div', { class: 'm-carrier-container' }, children)
      ])
    },
    renderDialogButtons (h, dialogData) {
      dialogData.footerHide = dialogData.btns === false
      const btns = dialogData.btns ?? this.btns
      //   console.log(([null, undefined].includes(btns) || btns.size < 1))
      if ([null, undefined].includes(btns) || btns.size < 1) {
        return []
      }

      //   const validateBtns = []
      //   for (const idx in btns) {
      //     const btn = btns[idx]
      //     let disabledVal = false
      //     if (!['', null, undefined].includes(btn.permission) && !this.hasPermission(btn.permission)) {
      //       disabledVal = true
      //     }
      //     const info = { disabled: disabledVal, ...btn }
      //     validateBtns.push(info)
      //   }
      return btns && btns.length
        ? h('div', { class: 'm-carrier-btns', slot: 'footer' },
          btns.map(btn => h(Button, {
            props: { size: this.size, ...btn },
            on: {
              click: this.publishClick.bind(this, btn, dialogData)
            }
          }, btn.label))
        )
        : []
    },
    async publishClick (operation, dialogData) {
      const instance = this.$refs[`default-${dialogData._index}`]
      const callback = dialogData[`on${operation.value.slice(0, 1).toUpperCase() + operation.value.slice(1)}`]
      if (instance &&
      instance[operation.value] &&
      typeOf(instance[operation.value], ['function', 'asyncfunction'])) {
        try {
          this.$set(operation, 'loading', true)
          const operationVoid = await instance[operation.value]()
          if (operationVoid === true) {
            return this.$set(operation, 'loading', false)
          } else {
            if (callback) {
              const callbackVoid = callback(operationVoid)
              if (callbackVoid === true) {
                return this.$set(operation, 'loading', false)
              } else {
                this.$set(operation, 'loading', false)
                this.back()
              }
            } else {
              this.$set(operation, 'loading', false)
              this.back()
            }
          }
        } catch (error) {
          return this.$set(operation, 'loading', false)
        }
      } else {
        if (callback) {
          const callbackVoid = callback()
          if (callbackVoid === true) {
            return this.$set(operation, 'loading', false)
          } else {
            this.$set(operation, 'loading', false)
            this.back()
          }
        } else {
          this.$set(operation, 'loading', false)
          this.back()
        }
      }
    }
  },

  render (h) {
    return h('div', { class: 'm-carrier' }, this.dialogs.map((d, i) => {
      d._index = i
      const slotFooter = this.renderDialogButtons(h, d)
      const slotDefault = this.renderDialogDefault(h, d)
      return h(Modal,
        {
          props: { customClass: 'm-carrier-elBody', ...d },
          ref: `model-${d._index}`,
          on: { 'on-visible-change': (v) => this.onVisibleChange(v, d) }
        },
        [slotDefault, slotFooter])
    }))
  }
}
</script>

<style scoped>
.m-carrier-body{
  max-height:70vh;
  overflow: auto;
}
</style>
